知道移動方向時要處理的項目(紀錄改變前的位置和方向)後,可以寫一連串的移動判斷
每次要移動時,檢查下列項目:
有了這三個判斷大概就做完7成的功能了
片段程式碼解析
let direct = [[1,0], [0, 1], [-1, 0], [0, -1]]; // right, down, left, up
const k_map = new Map();
k_map.set("ArrowRight", 0);
k_map.set("ArrowDown", 1);
k_map.set("ArrowLeft", 2);
k_map.set("ArrowUp", 3);
function getKey(e)
{
    let tmp_x, tmp_y;
    tmp_x = snake[snake_len-1].x;
    tmp_y = snake[snake_len-1].y;
    
    k_value = k_map.get(e.code); // get key code, and mapping to the direction value(0,1,2,3)
    
    // get the next position
    tmp_x += direct[k_value][0] * snake_sz;
    tmp_y += direct[k_value][1] * snake_sz;
    // 1. over boarder?
    if ((tmp_x >= max_len) || (tmp_x < 0) || (tmp_y >= max_width) || (tmp_y<0))
    {
        alert("game over");
        location.reload();
        return;
    }
    // 2. meet body?
    if (chk_meet_body(tmp_x, tmp_y) === true)
    {
        alert("game over");
        location.reload();
        return;
    }
    // 3. eat food?
    if (chk_eat(food_x, food_y) === true)
    {
        snake.push({x: tmp_x, y: tmp_y});
        ctx.fillRect(tmp_x, tmp_y, snake_sz, snake_sz);
        ctx.clearRect(snake[0].x, snake[0].y, snake_sz, snake_sz);
        add_food();
        return;
    }
    
    // ============== 判斷出方向更換後,需做的蛇身未來要轉換方向的紀錄========
    
    // snake head, 轉換方向前的蛇頭
    tmp_x = snake[snake_len-1].x;
    tmp_y = snake[snake_len-1].y;
    // store the history direction for snake body to move
    //tmp_map.set(cur_direct, {x:tmp_x, y:tmp_y});
    direct_record.push({direct: cur_direct, x:tmp_x, y:tmp_y});
    
    // 歷史紀錄完以後,開始處理蛇頭的新位置,並移除蛇尾
    tmp_x += direct[k_value][0] * snake_sz;
    tmp_y += direct[k_value][1] * snake_sz;
    if (chk_meet_sth(food_x, food_y) === true)
    {
        snake.push({x: tmp_x, y: tmp_y});
        ctx.fillRect(tmp_x, tmp_y, snake_sz, snake_sz);
        cur_direct = k_value;
        add_food();
        return;
    }
    snake.push({x: tmp_x, y: tmp_y});
    ctx.fillRect(tmp_x, tmp_y, snake_sz, snake_sz);
    // get the history direction and move 
    let tmp = direct_record[0].direct;
    tmp_x = snake[0].x + direct[tmp][0] * snake_sz;
    tmp_y = snake[0].y + direct[tmp][1] * snake_sz;
    
    // 碰到轉折點後,將歷史紀錄移除,蛇尾之後有新的方向移動
    if ((tmp_x == direct_record[0].x) && (tmp_y == direct_record[0].y))
    {
        direct_record.shift();
    }
    
    // 移除蛇尾
    ctx.clearRect(snake[0].x, snake[0].y, snake_sz, snake_sz);
    snake.shift();
    cur_direct = k_value;
}
現在的版本,蛇的移動都是靠鍵盤有按下才會動起來,所以剩下的三成指的是,能每隔一段時間區間後,蛇自己移動,這部分留著下篇待續。